﻿using System;
using System.Collections.Generic;
using UnityEngine;

// 导出位置信息的数据类

[Serializable]
public class AnimTransformData
{
    public string name;
    public int frameCount;

    //测试使用数据
    public float length;
    public float frameRate;

    [NonSerialized]
    public List<PositionData> posDatas;//数据导出中间集合
    [NonSerialized]
    public List<RotationData> rotDatas;//数据导出中间集合

    //完整的位置信息
    public List<TransformData> transDatas;

    public AnimTransformData()
    {
        posDatas = new List<PositionData>();
        rotDatas = new List<RotationData>();
    }


    //获取指定帧数的位置信息数据
    public PositionData GetPositionDataByFrame(int frame)
    {
        for (int i = 0; i < posDatas.Count; i++)
        {
            if (posDatas[i].frame == frame)
            {
                return posDatas[i];
            }
        }
        return null;
    }

    //获取指定帧数的旋转信息数据
    public RotationData GetRotationDataByFrame(int frame)
    {
        for (int i = 0; i < rotDatas.Count; i++)
        {
            if (rotDatas[i].frame == frame)
            {
                return rotDatas[i];
            }
        }
        return null;
    }

    public void AddPositionData(PositionData data)
    {
        posDatas.Add(data);
    }

    public void AddRotationData(RotationData data)
    {
        rotDatas.Add(data);
    }

    //未k帧的动画做插值。线性插值，舍弃
    public void lerpFrameData()
    {
        posDatas.Sort((a, b) => { return a.frame.CompareTo(b.frame); });
        rotDatas.Sort((a, b) => { return a.frame.CompareTo(b.frame); });

        int frame = Mathf.RoundToInt(length * frameRate);
        Debug.Log("动画帧数：" + frame);
        int frameCount = frame + 1;

        //包含全部帧数的集合
        transDatas = new List<TransformData>(frameCount);

        for (int i = 0; i < frameCount; i++)
        {
            TransformData data = new TransformData(0, i);
            transDatas.Add(data);

            //处理位置
            PositionData pos = GetPositionDataByFrame(i);
            if (pos != null)
            {
                data.position = pos.position;
            }
            else
            {
                //前一个有效值
                PositionData last = GetLastPosValue(i);
                //后一个有效值
                PositionData next = GetNextPosValue(i);
                float t = (float)(i - last.frame) / (next.frame - last.frame);
                Vector3 realPos = Vector3.Lerp(last.position, next.position, t);
                data.position = realPos;
            }

            //处理旋转
            RotationData rot = GetRotationDataByFrame(i);
            if (rot != null)
            {
                data.rotation = rot.rotation;
            }
            else
            {
                //前一个有效值
                RotationData last = GetLastRotValue(i);
                //后一个有效值
                RotationData next = GetNextRotValue(i);
                float t = (float)(i - last.frame) / (next.frame - last.frame);
                Vector3 realRot = Vector3.Lerp(last.rotation, next.rotation, t);
                data.rotation = realRot;
            }
        }
    }

    public void MergeFrameData()
    {
        posDatas.Sort((a, b) => { return a.frame.CompareTo(b.frame); });
        rotDatas.Sort((a, b) => { return a.frame.CompareTo(b.frame); });

        int frame = Mathf.RoundToInt(length * frameRate);
        Debug.Log("动画帧数：" + frame);
        this.frameCount = frame + 1;

        //包含全部帧数的集合
        transDatas = new List<TransformData>(frameCount);

        for (int i = 0; i < frameCount; i++)
        {
            TransformData data = new TransformData(0, i);
            transDatas.Add(data);

            //处理位置
            PositionData pos = GetPositionDataByFrame(i);
            if (pos != null)
            {
                data.position = pos.position;
            }

            //处理旋转
            RotationData rot = GetRotationDataByFrame(i);
            if (rot != null)
            {
                data.rotation = rot.rotation;
            }
        }
    }

    public float FrameToTime(int frame, float frameRate)
    {
        return (float)frame / frameRate;
    }

    PositionData GetLastPosValue(int frame)
    {
        for (int i = 0; i < posDatas.Count; i++)
        {
            if (posDatas[i].frame > frame)
            {
                if (i > 0)
                {
                    return posDatas[i - 1];
                }
            }
        }
        return null;
    }

    PositionData GetNextPosValue(int frame)
    {
        for (int i = posDatas.Count - 1; i > -1; i--)
        {
            if (posDatas[i].frame < frame)
            {
                if (i < posDatas.Count - 1)
                {
                    return posDatas[i + 1];
                }
            }
        }
        return null;
    }
    RotationData GetLastRotValue(int frame)
    {
        for (int i = 0; i < rotDatas.Count; i++)
        {
            if (rotDatas[i].frame > frame)
            {
                if (i > 0)
                {
                    return rotDatas[i - 1];
                }
            }
        }
        return null;
    }

    RotationData GetNextRotValue(int frame)
    {
        for (int i = rotDatas.Count - 1; i > -1; i--)
        {
            if (rotDatas[i].frame < frame)
            {
                if (i < rotDatas.Count - 1)
                {
                    return rotDatas[i + 1];
                }
            }
        }
        return null;
    }

    public Vector3 GetPosition(float time)
    {
        if (time <= length)
        {
            int frame = Mathf.RoundToInt(time * frameRate);
            Debug.Log("计算出帧数：" + frame);
            PositionData data = GetPositionDataByFrame(frame);
            if (data != null)
                return data.position;
        }
        return Vector3.zero;
    }

    public Vector3 GetRotation(float time)
    {
        if (time <= length)
        {
            int frame = Mathf.RoundToInt(time * frameRate);
            RotationData data = GetRotationDataByFrame(frame);
            if (data != null)
                return data.rotation;
        }
        return Vector3.zero;
    }

    //-----------------------导出的数据调用接口---------------

    public TransformData GetRealData(float time)
    {
        if (time <= length)
        {
            int frame = Mathf.RoundToInt(time * frameRate);
            // Debug.Log("time=" + time + " 计算出帧数：" + frame);
            for (int i = 0; i < transDatas.Count; i++)
            {
                if (transDatas[i].frame == frame)
                {
                    return transDatas[i];
                }
            }
        }
        return null;
    }

    public Vector3 GetRealPosition(float time)
    {
        if (time <= length)
        {
            TransformData data = GetRealData(time);
            if (data != null)
                return data.position;
        }
        return Vector3.zero;
    }

    public Vector3 GetRealRotation(float time)
    {
        if (time <= length)
        {
            TransformData data = GetRealData(time);
            if (data != null)
                return data.rotation;
        }
        return Vector3.zero;
    }
    public void WriteToJson()
    {
        string json = JsonUtility.ToJson(this, true);
        string path = AnimConfig.folderPath + "/" + name + "_trans.json";
        System.IO.File.WriteAllText(path, json);
    }
}
[Serializable]
public class PositionData
{
    public float time;//时间
    public int frame; //帧数
    public Vector3 position;

    public PositionData(float time, int frame)
    {
        this.time = time;
        this.frame = frame;
        position = Vector3.zero;
    }
}

[Serializable]
public class RotationData
{
    public float time;//时间
    public int frame; //帧数
    public Vector3 rotation;

    public RotationData(float time, int frame)
    {
        this.time = time;
        this.frame = frame;
        rotation = Vector3.zero;
    }
}

[Serializable]
public class TransformData
{
    public float time;//时间
    public int frame; //帧数
    public Vector3 position;
    public Vector3 rotation;

    public TransformData(float time, int frame)
    {
        this.time = time;
        this.frame = frame;
        position = Vector3.zero;
        rotation = Vector3.zero;
    }
}
